# -*- coding: utf-8 -*-
""" A Height Widget that handles Ellipsoidical and Orthometric heights

    :Author:
      - 20111202-20120110 Roberto Vidmar

    :Revision:  $Revision: 52 $
                $Date: 2012-11-12 09:07:15 +0000 (Mon, 12 Nov 2012) $

    :Copyright: 2011-2012
                Nicola Creati <ncreati@inogs.it>
                Roberto Vidmar <rvidmar@inogs.it>

    :License: MIT/X11 License (see :download:`license.txt
                               <../../license.txt>`)
"""

from qtCompat import Qt, QtCore, QtGui, Signal
QCA = QtCore.QCoreApplication

from abstractFeditor import FEditor

#===============================================================================
class HeightWidget(QtGui.QWidget):
  """ A Height Widget that handles Ellipsoidical and Geoidical heights.
  """
  textEditedSignal = Signal(object)
  ELL = 0
  ORTHO = 1

  def __init__(self, *args, **kargs):
    """ Create a new instance of the widget.

        The first argument, if present, is the value to assign.

        The following keyword arguments are understood:

        - hchr      : height description strings
                    Default is (u"ell", u"ortho")
        - invalid   : this is the value that we consider **INVALID**
                    Default is -9999.99
        - ell2Ortho : float to add to ellipsoidical height to get orthometric
                    height. Default is None (**NO ORTHOMETRIC HEIGHT**)
        - decimals  : number of decmals for the representation
                    Default is 3
        - heightLen : number of figures in height (`unused?`)
                    Default is 4
        - rep       : representation to show after creation.
                    Default is :class:`ELL`
        - align     : alignment of the widget.
                    Default is Qt.AlignRight
        - readonly  : read only attribute.
                    Default is False
    """
    if len(args) > 1:
      value = args[1]
    else:
      value = None
    if len(args) > 0:
      parent = args[0]
    else:
      parent = None
    super(HeightWidget, self).__init__(parent)

    hchrs = kargs.pop('hchr', (u"ell", u"ortho")) # Ell/Ortho
    self.invalid = kargs.pop('invalid', -9999.99)
    self._ell2Ortho = kargs.pop('ell2Ortho', None)
    self.decimals = kargs.pop('decimals', 3)
    self.heightLen = kargs.pop('heightLen', 4)
    rep = kargs.pop('rep', self.ELL)
    self.align = kargs.pop('align', Qt.AlignRight)
    self.readonly = kargs.pop('readonly', False)

    self.swidget = QtGui.QStackedWidget()
    self.swidget.setContentsMargins(0, 0, 0, 0)
    for editor, toolTip in zip(
      (FEditor(self, hchrs[0]), FEditor(self, hchrs[1])),
      (QCA.translate("HeightWidget",
      "Enter here ellipsoidical height in meters"),
      QCA.translate("HeightWidget",
      "Enter here orthometric height in meters"))):
      editor.setToolTip(toolTip)
      self.swidget.addWidget(editor)
      editor.setReadOnly(self.readonly)
      editor.textEdited.connect(self.textEdited)

    if self._ell2Ortho is None:
      # We cannot change orthometric height
      self.swidget.widget(1).setReadOnly(True)
    else:
      orthoH = value + self._ell2Ortho
      self.swidget.widget(1).setValue(orthoH)

    # Representation
    self.setRep(rep)

    # Layout
    self._layout = QtGui.QHBoxLayout(self)
    self._layout.addWidget(self.swidget, alignment=Qt.AlignLeft|Qt.AlignVCenter)
    self._layout.setContentsMargins(0, 0, 0, 0)

    if value is not None:
      self.setEllH(value)

  def textEdited(self, text):
    """ Update all widgets except the one that sent the signal

      :param text: the content of the editor widget
      :type text: string
      :raises:
    """
    # Update other widgets:
    if self.sender() == self.swidget.widget(0):
      # Ellipsoidical height changed
      if self._ell2Ortho is None:
        self.swidget.widget(1).setReadOnly(True)
      else:
        self.swidget.widget(1).setValue(self.sender().fvalue() +
          self._ell2Ortho)
    else:
      # Orthometric height changed
      self.swidget.widget(0).setValue(self.sender().fvalue() - self._ell2Ortho)
    self.textEditedSignal.emit(self.ellH())

  def rep(self):
    """ Return current representation:

      :returns: widget current representation
      :rtype: any of :class:`ELL`, :class:`ORTHO`
      :raises:
    """

    return self.swidget.currentIndex()

  def setRep(self, rep=ELL):
    """ Set widget aspect (representation) according to rep:

    :param rep: new representation
    :type rep: any of :class:`ELL`, :class:`ORTHO`
    :raises:
    """
    self.swidget.setCurrentIndex(rep)

  def ellH(self):
    """ Return ellipsoidical height

      :returns: ellipsoidical height
      :rtype: float
      :raises:
    """
    return float(self.swidget.widget(0).value())

  def orthoH(self):
    """ Return orthometric height

      :returns: orthometric height or None
      :rtype: float or None
      :raises:
    """
    if self._ell2Ortho is None:
      return None
    else:
      return float(self.swidget.widget(1).svalue())

  def ell2Ortho(self):
    """ Return ellipsoidical to orthometric height difference

      :returns: ellipsoidical to orthometric height difference
      :rtype: float
      :raises:
    """
    return self._ell2Ortho

  def setEll2Ortho(self, ell2Ortho):
    """ Set ellipsoidical to orthometric height (geoid) difference

      :param ell2Ortho: ellipsoidical to orthometric height difference
      :type ell2Ortho: float
      :raises:
    """
    self._ell2Ortho = ell2Ortho
    if self._ell2Ortho is None:
      orthoH = self.invalid
      readOnly = True
      self.setRep(0)
    else:
      orthoH = self.swidget.widget(0).fvalue() + ell2Ortho
      readOnly = False

    self.swidget.widget(1).setValue(orthoH)
    self.swidget.widget(1).setReadOnly(readOnly)

  def setEllH(self, ellh):
    """ Set ellipsoidical height in meters

      :param ellh: ellipsoidical height
      :type ell2Ortho: float
      :raises:
    """
    self.swidget.widget(0).setValue(ellh)
    if self._ell2Ortho is not None:
      self.swidget.widget(1).setValue(ellh + self._ell2Ortho)
    return
